#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
/**
 * Executa os programas
 *
 * params: piped - verificador de execucao em pipe
 *         bg    - verificador para execucao em background

 */
void executa(char **args, int bg)
{
    pid_t filho;
    int status;
    
    if(filho = fork() == 0){
        int i = execv(args[0], args);
        if(i < 0){
            printf("%s: comando não encontrado\n", args[0]);
            exit(1);
        }
    }
    if( !bg ) {
        waitpid(filho, &status, 0);
    }
}

/**
 * Executa vários comandos em pipe
 *
 */
void executa_piped( char **cmd, int cmdIndex )
{
    int **fd;
    int n;
    int status;
    int n_comandos;
    pid_t *pid;

    n_comandos = getArrayLength(cmd); 
    
    pid = (pid_t*)malloc(sizeof(pid_t) * n_comandos);
    
    
    fd = (int**)malloc(sizeof(int*) * (n_comandos - 1));
    for (n=0; n < (n_comandos - 1); n++)
        fd[n] = (int*)malloc(sizeof(int)*2);
      
    for (n=0; n < (n_comandos - 1); n++)
        pipe(fd[n]);
        
    for (n=0; n < n_comandos; n++){
    
        pid[n] = fork();
        
        if (pid[n] == 0){
            int i;
               
            // todas as execuçoes, exceto a primeira, recebem a entrada da execuçao
            // anterior
            if (n != 0){
                dup2(fd[n-1][0], STDIN_FILENO);
            }
            
            // todas as execuções, exceto a ultima, encaminham sua saida para a proxima execução
            if (n != n_comandos-1){
                dup2(fd[n][1], STDOUT_FILENO);
            } 

            // fexamento dos pipes
            for (i=0; i< (n_comandos-1); i++)
            {
                close(fd[i][0]);
                close(fd[i][1]);
            }
            
            break;
        }
    }
    
    // execução dos comandos
    for (n = 0; n < n_comandos; n++){
        if (pid[n] == 0){
            char** args = (char **) split(cmd[n], " ");
            
            execvp(args[0], args);
            
            printf("comando %s inválido.\n", args[0]);
            exit(0);
        }
    }
    waitpid(pid[n], &status, 0);
}
